package com.lp.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
import com.lp.bean.IotSensorInfo;
import com.lp.bean.ProDictionaryInfo;
import com.lp.bo.IotNodeInfoBO;
import com.lp.bo.IotSceneInfoBO;
import com.lp.bo.ProDictionaryInfoBO;
import com.lp.cache.CacheName;
import com.lp.cache.ProCacheUtil;
import com.lp.common.Code;
import com.lp.common.CodeIot;
import com.lp.dao.BaseDao;
import com.lp.service.IotNodeInfoService;
import com.lp.util.ObjectUtil;
import com.lp.util.PageBean;
import com.lp.util.ResultMapUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @className: IaasImportListener
 * @Author zhengxm_csd
 * @Date 2024/1/17
 */
@Slf4j
public class DeviceImportListener extends AnalysisEventListener<IotNodeInfoBO> {
    private IotNodeInfoService service;
    private BaseDao dao;
    private Map<String, Object> resultMap;
    private List<IotNodeInfoBO> list = new ArrayList<>();
    private List<String> errorList = new ArrayList<>();

    enum PROTOCOL_MAP {
        TCP(83, "TCP", 300),
        MQTT(84, "MQTT", 305),
        ;
        public Integer code;
        private String name;
        private Integer pCode;

        PROTOCOL_MAP(Integer code, String name, Integer pCode) {
            this.code = code;
            this.pCode = pCode;
            this.name = name;
        }

        public Integer getCode() {
            return code;
        }

        public Integer getPcode() {
            return pCode;
        }

        public String getName() {
            return name;
        }

        public static Integer getCodeByName(String name) {
            PROTOCOL_MAP[] manufacturers = values();
            for (PROTOCOL_MAP manufacturer : manufacturers) {
                if (StringUtils.equals(manufacturer.getName(), name)) {
                    return manufacturer.getCode();
                }
            }
            return null;
        }

        public static Integer getPcodeByName(String name) {
            PROTOCOL_MAP[] manufacturers = values();
            for (PROTOCOL_MAP manufacturer : manufacturers) {
                if (StringUtils.equals(manufacturer.getName(), name)) {
                    return manufacturer.getPcode();
                }
            }
            return null;
        }
    }

    public DeviceImportListener(IotNodeInfoService iotNodeInfoService, BaseDao dao, Map<String, Object> resultMap) {
        this.service = iotNodeInfoService;
        this.resultMap = resultMap;
        this.dao = dao;
    }

    public List<IotNodeInfoBO> getDataList() {
        return list;
    }

    public List<String> getErrorList() {
        return errorList;
    }

    @Override
    public void invoke(IotNodeInfoBO iotNodeInfoBO, AnalysisContext analysisContext) {
        //校验数据
        Integer rowIndex = analysisContext.readRowHolder().getRowIndex();
        iotNodeInfoBO = verifyData(iotNodeInfoBO, rowIndex);
        if (rowIndex > 0 && iotNodeInfoBO != null) {
            list.add(rowIndex - 1, iotNodeInfoBO);
        }
    }

    private IotNodeInfoBO verifyData(IotNodeInfoBO iotNodeInfoBO, Integer rowIndex) {
        log.info("{}", iotNodeInfoBO);
        //========导入数据默认配置=========
        if (iotNodeInfoBO.getFrequency()==null){
            iotNodeInfoBO.setFrequency(15);
        }
        if (iotNodeInfoBO.getSeq()==null){
            iotNodeInfoBO.setSeq(1);
        }
        if (StringUtils.isEmpty(iotNodeInfoBO.getLonLat())){
            iotNodeInfoBO.setLonLat("119.924657,31.234461");
        }
        if (StringUtils.isEmpty(iotNodeInfoBO.getIot_node_type_name())) {
            //默认MQTT——DGRID_MQTT
            iotNodeInfoBO.setIot_node_type(84);
            iotNodeInfoBO.setPCode(300);
            iotNodeInfoBO.setIot_protocal_category("ProtocalMing");
            //========导入数据默认配置=========
        } else {
            iotNodeInfoBO.setIot_node_type(PROTOCOL_MAP.getCodeByName(iotNodeInfoBO.getIot_node_type_name()));
            iotNodeInfoBO.setPCode(PROTOCOL_MAP.getPcodeByName(iotNodeInfoBO.getIot_node_type_name()));
            if (iotNodeInfoBO.getIot_node_type() == null) {
                log.warn("第{}行数据未设置正确的【Device communication protocol】，本次导入已忽略", rowIndex);
                errorList.add("第" + rowIndex + "行数据未设置正确的【Device communication protocol】，本次导入已忽略");
                return null;
            }
            ResultMapUtils.putData(resultMap, ProCacheUtil.getCache(CacheName.DICTIONARY_RELATION, "300", new ProDictionaryInfoBO()).getSub());
            List<ProDictionaryInfo> sub = ProCacheUtil.getCache(CacheName.DICTIONARY_RELATION, "300", new ProDictionaryInfoBO()).getSub();
            if (sub.size() > 0) {
                for (ProDictionaryInfo proDictionaryInfo : sub) {
                    if (StringUtils.equalsIgnoreCase(iotNodeInfoBO.getIot_protocal_category_name(), proDictionaryInfo.getName())) {
                        iotNodeInfoBO.setIot_protocal_category(proDictionaryInfo.getDictionary_name());
                    }
                }
            }
        }

        if (iotNodeInfoBO.getIot_protocal_category() == null) {
            log.warn("第{}行数据未设置正确的【Data Protocol】，本次导入已忽略", rowIndex);
            errorList.add("第" + rowIndex + "行数据未设置正确的【Data Protocol】，本次导入已忽略");
            return null;
        }

        PageBean pageBean = new PageBean();
        pageBean.setPaged(1);
        pageBean.setPageSize(Integer.MAX_VALUE);
        IotSceneInfoBO iotSceneInfoBO = new IotSceneInfoBO();
        iotSceneInfoBO.setName(iotNodeInfoBO.getScene_name());
        List<IotSceneInfoBO> list = dao.selectList("IotSceneInfo.selectSceneInfo", iotSceneInfoBO, pageBean);
        if (ObjectUtil.isEmpty(list)) {
            log.warn("第{}行数据未设置正确的【Project Name】，本次导入已忽略", rowIndex);
            errorList.add("第" + rowIndex + "行数据未设置正确的【Project Name】，本次导入已忽略");
            return null;
        }
        iotNodeInfoBO.setScene_id(list.get(0).getId());
        iotNodeInfoBO.setName(iotNodeInfoBO.getDevice_code());
        return iotNodeInfoBO;
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 所有数据解析完成后的逻辑
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        log.info("导入有效数据共{}条", list.size());
        add(list);

    }

    private void add(List<IotNodeInfoBO> list) {
        for (IotNodeInfoBO obj : list) {
            if (ObjectUtil.isNotEmpty(obj.getScene_id())) {
                IotNodeInfoBO nodeInfo = ProCacheUtil.getCache(CacheName.NODEINFO_DEVICECODE, obj.getDevice_code());
                // 判断device_code是否重复
                if (ObjectUtil.isNotEmpty(nodeInfo)) {
                    ResultMapUtils.putStatusCode(resultMap, Code.ResponseCode.IotInfo.DEVICE_CODE_EXIST);
                } else {
                    obj.setIot_node_status(CodeIot.DEVICE_STATUS.UNCONTECT);
                    obj.setMtime(new Date());
                    resultMap = service.saveNodeInfo(obj);
                    //配置传感器
                    configSensor(obj.getId());
                }
            } else {
                ResultMapUtils.putStatusCode(resultMap, Code.ResponseCode.SystemCode.PARAM_ERROR);
            }
            if (ResultMapUtils.isOk(resultMap)) {
                ProCacheUtil.addCache(CacheName.NODEINFO, obj.getId().toString(), obj);
                ProCacheUtil.addCache(CacheName.NODEINFO_DEVICECODE, obj.getDevice_code(), obj);
            }
        }

    }

    private Integer configSensor(Integer nodeId) {
        int result = 0;
        //查询传感器模板
        PageBean pageBean = new PageBean();
        pageBean.setPaged(1);
        pageBean.setPageSize(Integer.MAX_VALUE);
        IotSensorInfo iotSensorInfo = new IotSensorInfo();
        //44为模板设备id
        iotSensorInfo.setNode_id(44);
        List<IotSensorInfo> list = dao.selectList("IotSensorInfo.selectList", iotSensorInfo, pageBean);
        for (IotSensorInfo sensorInfo : list) {
            sensorInfo.setNode_id(nodeId);
            result = dao.insert("IotSensorInfo.insert", sensorInfo);
        }
        return result;

    }

    @Override
    public void onException(Exception exception, AnalysisContext context) {
        if (exception instanceof ExcelDataConvertException) {
            ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception;
            log.error("第{}行，第{}列解析异常，数据为:{}", excelDataConvertException.getRowIndex(),
                    excelDataConvertException.getColumnIndex(), excelDataConvertException.getCellData());
            errorList.add("第" + excelDataConvertException.getRowIndex() + "行，第"
                    + excelDataConvertException.getColumnIndex() + "列解析异常，数据为:" + excelDataConvertException.getCellData());
        } else {
            ReadRowHolder readRowHolder = context.readRowHolder();
            Integer rowIndex = readRowHolder.getRowIndex();
            log.error("第{}行数据处理异常，异常信息：{}", rowIndex, exception.getMessage());
            errorList.add("第" + rowIndex + "行数据处理异常，异常信息：" + exception.getMessage());
            exception.printStackTrace();
        }
    }
}

